﻿/**
* @authors <darl2ng@gmail.com, ngocanh.ngo@gmail.com>
* @version 0.9
* Copyright 2010
* 
* The MIT License
* Copyright (c) 2010 <darl2ng@gmail.com, ngocanh.ngo@gmail.com>
* 
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
* 
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
* 
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.ng.ResHelp {

	import flash.display.Sprite;
	import flash.utils.getDefinitionByName;
	import XML;
	
	public class c_ResHelper {
		
		static private var __Instance:c_ResHelper;

		protected var __XML:XML;				
		protected var __ResLoader:c_ResLoader;
		protected var __MovieClipClassReference:Class;
		
		static public function GetInstance():c_ResHelper {
			if(__Instance == null)
				__Instance = new c_ResHelper();
			return __Instance;
		}
		public function c_ResHelper() {
			__MovieClipClassReference = getDefinitionByName('flash.display.MovieClip') as Class;
		}
		
		public function init(p_ResLoader:c_ResLoader):c_ResHelper {
			__ResLoader = p_ResLoader;			
			__XML = p_ResLoader.xml;
			if (__ResLoader.isLoaded) {
				registerControlerClasses();
			} else {
				throw new Error("c_ResHelper::ResLoader[NotReady]");
			}
		}
		
		public function get ResLoader():c_ResLoader {
			return __ResLoader;
		}
		public function get xml():XML {
			return __XML;
		}
		
		protected function registerControlerClasses():void {
			for each (var item:XML in __XML.Classes.Class) {
				var id:String = item.attribute("id");
				var cl:Class;
				try {
					cl = getDefinitionByName(id) as Class;
				} catch (e:ReferenceError) {
					throw new Error("ClassNotExist[" + id +"]");
				}
				if (cl != null) {
					__ResLoader.classes[id] = cl;
				}
			}
		}
		public function setFrameById(o:Object,frame_id:String):void {
			//TODO: this should be unique but people are crazy sometimes :-)
			for each (var frame:XML in __XML.Presentation.Frame.(@id == frame_id)) {
				if (frame.length() > 1) {
					throw new Error("c_ResHelper::FrameIdNotUnique[" + frame_id +"]");
				}
				fetchChildren(frame.Element, o as Sprite);
				o.name = frame_id;
				c_Builder.setAttributes(frame, o , __MovieClipClassReference);
			}
		}
		public function getFrameById(frame_id:String):Sprite{
			var fr:Sprite= new Sprite();
			setFrameById(fr, frame_id);
			return fr;
		}
		/**
		 * 
		 * @param	id
		 */
		public function getSoundById(id:String) {
			
		}
		/**
		 * 
		 * @param	id
		 */
		public function getBitmapById(id:String) {
			
		}
		public function setElementById(o:Object,frame_id:String,id:String):void {
			for each (var element:XML in __XML.Presentation.Frame.(@id == frame_id).Element.(@id == id)) {
				if (element.length() > 1) {
					throw new Error("c_ResHelper::ElementIdNotUnique[" + frame_id +","+id+"]");
				}
				c_Builder.setAttributes(element,o, __MovieClipClassReference );
			}			
		}		
		public function getClassById(id:String):Class {
			return __ResLoader.getClassById(id);
		}
		protected function fetchChildren(elements:XMLList, fr:Object):void{
			for each (var item:XML in elements) {
				var cl:Class;
				var e:Object;
				var id:String = item.attribute('class');
				if (id == null || id == '') {
					//every element in <Presentation> must have a correct class attribute
					throw new Error("c_ResHelper::fetchChildren[null]");
				}
				cl = getClassById(id);
				if (cl!=null) {
					e = new cl();
					e.name = item.attribute("id");
					if ("@controler" in item) { //correct way to check availability of an attribute
						var c:c_Controler;
						var ccl:Class;
						ccl = getClassById(item.attribute('controler'));
						if (ccl != null) {
							c = new ccl();
							e.controler = c;//IMPORTANT: using dynamic class here
							e.controler.skin = e;//IMPORTANT: using c_Controler class here
						}										
					}					
					fr.addChild(e);
					c_Builder.setAttributes(item, e, __MovieClipClassReference);	
					//parse and add children recursively if need to					
					if (item.Element.length() > 0) {
						fetchChildren(item.Element, e);
					}				
				}						
			}			
		}
	}
}